
/**
  ******************************************************************************
  * Copyright 2021 The grapilot Authors. All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  * 
  * @file       mavproxy_dev.c
  * @author     baiyang
  * @date       2021-7-21
  ******************************************************************************
  */

/*----------------------------------include-----------------------------------*/
#include <rtdevice.h>
#include <rthw.h>
#include <rtthread.h>

#include <string.h>
#include "shell.h"

#include "mavproxy_dev.h"
#include <common/console/console.h>
#include <serial_manager/gp_serial.h>
/*-----------------------------------macro------------------------------------*/
#define MAVPROXY_DEV_CHAN_NUM       2

#define MAVPROXY_CHAN1_DEVICE_NAME "serial1"
#define MAVPROXY_CHAN2_DEVICE_NAME "vcom"

#define OS_ENTER_CRITICAL        rt_enter_critical()
#define OS_EXIT_CRITICAL         rt_exit_critical()
/*----------------------------------typedef-----------------------------------*/

/*---------------------------------prototype----------------------------------*/

/*----------------------------------variable----------------------------------*/
static rt_device_t _mavproxy_dev = RT_NULL;
static uint8_t _dev_chan;

static char chan_device[MAVPROXY_DEV_CHAN_NUM][10] = {
    {MAVPROXY_CHAN1_DEVICE_NAME},
    {MAVPROXY_CHAN2_DEVICE_NAME},
};

/*-------------------------------------os-------------------------------------*/

/*----------------------------------function----------------------------------*/
static int device_switch(char* dev_name)
{
    rt_device_t new_dev;

    new_dev = rt_device_find(dev_name);

    if(new_dev == RT_NULL) {
        return 1;
    }

    if(rt_device_open(new_dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_DMA_RX
                      | RT_DEVICE_FLAG_DMA_TX) != RT_EOK) {
        console_printf("mavproxy device open fail\n");
        return 1;
    }

    if(_mavproxy_dev) {
        /* close old device */
        rt_device_close(_mavproxy_dev);
    }

    _mavproxy_dev = new_dev;

    return 0;
}

static int switch_chan_if_needed(uint8_t new_chan)
{
    if(new_chan != _dev_chan && new_chan < MAVPROXY_DEV_CHAN_NUM) {
        if(device_switch(chan_device[new_chan]) == 0) {
            _dev_chan = new_chan;
            return 1;
        }
    }

    return 0;
}

uint8_t mavproxy_dev_used_channel(void)
{
    return _dev_chan;
}

rt_size_t mavproxy_dev_sync_write(uint8_t chan, const void* buffer, uint32_t len)
{
    rt_size_t size;

    switch_chan_if_needed(chan);

    /* write data to device */
    size = rt_device_write(_mavproxy_dev, 0, buffer, len);

    return size;
}

rt_size_t mavproxy_dev_sync_read(uint8_t chan, void* buffer, uint32_t len)
{
    rt_size_t cnt = 0;

    switch_chan_if_needed(chan);

    /* try to read data */
    cnt = rt_device_read(_mavproxy_dev, 0, buffer, len);

    return len;
}

rt_size_t mavproxy_dev_write(uint8_t chan, const void* buffer, uint32_t len, int32_t timeout)
{
    rt_size_t size;

    switch_chan_if_needed(chan);

    /* write data to device */
    size = rt_device_write(_mavproxy_dev, 0, buffer, len);

    return size;
}

rt_size_t mavproxy_dev_read(uint8_t chan, void* buffer, uint32_t len, int32_t timeout)
{
    rt_size_t cnt = 0;

    switch_chan_if_needed(chan);

    /* try to read data */
    cnt = rt_device_read(_mavproxy_dev, 0, buffer, len);

    return cnt;
}

int mavproxy_dev_init(uint8_t chan)
{
    if(chan >= MAVPROXY_DEV_CHAN_NUM) {
        console_printf("illegal device channel\n");
        return 1;
    }

    _dev_chan = chan;

    _mavproxy_dev = rt_device_find(chan_device[_dev_chan]);

    if(_mavproxy_dev == RT_NULL) {
        console_printf("err, can not find %d device\n", chan_device[_dev_chan]);
        return 1;
    }

    return 0;
}

/*------------------------------------test------------------------------------*/


